﻿using System;

namespace DimensionsHelper.Common.Utils;

/// <summary>
///     替换表达式的解析器
/// </summary>
public class ReplacerParser
{
    private readonly Replacer _replacer;
    private readonly string _text;
    private int _pos;

    private ReplacerParser(string text)
    {
        _text = text;
        _pos = 0;
        _replacer = new Replacer();
    }

    private char CurrentChar()
    {
        if (_pos >= _text.Length)
        {
            return '\0';
        }

        return _text[_pos];
    }

    private char NextChar()
    {
        _pos++;
        return _pos >= _text.Length ? '\0' : _text[_pos];
    }

    private PlaceHolder GetLastPlaceHolder(PlaceHolderKind kind)
    {
        if (kind != PlaceHolderKind.Identifier &&
            _replacer.PlaceHolders.Count > 0 &&
            _replacer.PlaceHolders[_replacer.PlaceHolders.Count - 1].Kind == kind)
        {
            return _replacer.PlaceHolders[_replacer.PlaceHolders.Count - 1];
        }

        var holder = new PlaceHolder(kind);
        _replacer.Append(holder);
        return holder;
    }

    private void ReadTextInCurly(PlaceHolder holder)
    {
        var ch = CurrentChar();
        while (ch != '\0' && ch != '}')
        {
            holder.TextBuilder.Append(ch);
            ch = NextChar();
        }

        if (ch == '\0')
        {
            throw new Exception("未终结的花括号");
        }
    }

    private bool Parse()
    {
        var ch = CurrentChar();

        if (ch == '\0')
        {
            return false;
        }

        if (ch == '$')
        {
            // ${
            if (_text.Length - _pos > 1 && _text[_pos + 1] == '{')
            {
                _pos += 2;
                var id = GetLastPlaceHolder(PlaceHolderKind.Identifier);
                ReadTextInCurly(id);
                NextChar();
                return true;
            }
            // $r{  |  $a{

            if (_text.Length - _pos > 2
                && (_text[_pos + 1] == 'r' || _text[_pos + 1] == 'a')
                && _text[_pos + 2] == '{')
            {
                var kind = _text[_pos + 1] == 'r' ? PlaceHolderKind.Remaining : PlaceHolderKind.Alias;
                _pos += 3;
                var holder = GetLastPlaceHolder(kind);
                ReadTextInCurly(holder);
                NextChar();
                return true;
            }
        }

        // 文本内容
        var textHolder = GetLastPlaceHolder(PlaceHolderKind.Text);
        textHolder.TextBuilder.Append(ch);
        NextChar();

        return true;
    }

    /// <summary>
    ///     使用<see cref="Replacer" />定义的占位符读取表达式字符。
    /// </summary>
    public static Replacer Parse(string expression)
    {
        var parser = new ReplacerParser(expression);

        while (parser.Parse())
        {
        }

        return parser._replacer;
    }
}